﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
using Excel = Microsoft.Office.Interop.Excel;


// TODO:  Follow these steps to enable the Ribbon (XML) item:

// 1: Copy the following code block into the ThisAddin, ThisWorkbook, or ThisDocument class.

//  protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
//  {
//      return new Ribbon();
//  }

// 2. Create callback methods in the "Ribbon Callbacks" region of this class to handle user
//    actions, such as clicking a button. Note: if you have exported this Ribbon from the Ribbon designer,
//    move your code from the event handlers to the callback methods and modify the code to work with the
//    Ribbon extensibility (RibbonX) programming model.

// 3. Assign attributes to the control tags in the Ribbon XML file to identify the appropriate callback methods in your code.  

// For more information, see the Ribbon XML documentation in the Visual Studio Tools for Office Help.


namespace ChartDemo {
    [ComVisible(true)]
    public class Ribbon : Office.IRibbonExtensibility {
        private Office.IRibbonUI ribbon;

        public Ribbon() {
        }

        #region IRibbonExtensibility Members

        public string GetCustomUI(string ribbonID) {
            return GetResourceText("ChartDemo.Ribbon.xml");
        }

        #endregion

        #region Ribbon Callbacks
        //Create callback methods here. For more information about adding callback methods, select the Ribbon XML item in Solution Explorer and then press F1

        public void Ribbon_Load(Office.IRibbonUI ribbonUI) {
            this.ribbon = ribbonUI;
        }

        #endregion

        #region Helpers

        private static string GetResourceText(string resourceName) {
            Assembly asm = Assembly.GetExecutingAssembly();
            string[] resourceNames = asm.GetManifestResourceNames();
            for (int i = 0; i < resourceNames.Length; ++i) {
                if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0) {
                    using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i]))) {
                        if (resourceReader != null) {
                            return resourceReader.ReadToEnd();
                        }
                    }
                }
            }
            return null;
        }

        #endregion

        public void btnUpdate_Click(Office.IRibbonControl sender) {
            UpdateCharts();
        }

        private void UpdateCharts() {
            ExcelProcessManager pm = new ExcelProcessManager();
            pm.Lock();

            foreach (Word.Bookmark mark in Globals.ThisAddIn.Application.ActiveDocument.Bookmarks) {
                // must cast
                // the inlineshape does not contain the chart property in pia.
                Interop.Word.InlineShapes inlineShapes = (Interop.Word.InlineShapes)mark.Range.InlineShapes;

                if (inlineShapes.Count > 0) {
                    try {
                        object Name = new object();
                        Name = mark.Name;

                        Object[,] obj = new Object[11, 3];
                        // fill data to obj
                        /*     ------------------------------------
                         *     |              |  收入  |  支出   |
                         *     ------------------------------------
                         *     |  2012/03/01  |  1023.2 |  304.23  |
                         *     -------------------------------------
                         *     |  2012/03/02  |  1123.2 |  314.23  |
                         *     -------------------------------------
                         *     |  2012/03/03  |  1223.2 |  674.23  |
                         *     -------------------------------------
                         *     |  2012/03/04  |  1043.2 |  124.23  |
                         *     -------------------------------------
                         *     |  2012/03/05  |  1083.2 |  384.23  |
                         *     -------------------------------------
                         *     |  2012/03/06  |  923.2  |  404.23  |
                         *     -------------------------------------
                         *     |  2012/03/07  |  2023.2 |  305.23  |
                         *     -------------------------------------
                         *     |  2012/03/08  |  1623.2 |  303     |
                         *     -------------------------------------
                         *     |  2012/03/09  |  1403.2 |  314.23  |
                         *     -------------------------------------
                         *     |  2012/03/10  |  1003.2 |  340     |
                         *     -------------------------------------
                         */
                        //添加横向第一列作为标题
                        obj[0, 0] = string.Empty;
                        obj[0, 1] = "收入";
                        obj[0, 2] = "支出";

                        DateTime dt = new DateTime(2012, 3, 1);
                        Random rnd = new Random();
                        int last = 1000;
                        // fill data
                        for (int i = 1; i < 11; i++) {
                            obj[i, 0] = dt.ToString("yyyy/MM/dd");
                            obj[i, 1] = last + rnd.Next(i, 100);
                            obj[i, 2] = last - rnd.Next(i, 100);
                            last = (int)obj[i, 1];
                            dt = dt.AddDays(1);
                        }

                        Interop.Word.Chart chart = inlineShapes[1].Chart;
                        ChartUpdate(chart, Name.ToString(), obj);
                    } catch (Exception ex) {
                        //logger.Warn("Chart update failed!", ex);
                    }
                }
            }

            pm.Release();
        }

        protected void ChartUpdate(Interop.Word.Chart chart, string bookMark, Object[,] dataArr) {
            if (chart == null) {
                //logger.Warn("Word.Chart is null!");
                return;
            }

            if (dataArr == null) {
                //logger.Warn("Data is null!");
                return;
            }

            Object oMissing = System.Reflection.Missing.Value;
            Interop.Word.Chart chrt;
            Microsoft.Office.Interop.Excel.Workbook wb = null;

            Object bk = bookMark;
            try {
                //xlApp.ScreenUpdating = false;
                chrt = chart;

                if (chrt.ChartData == null) {
                    //logger.Warn("chart.ChartData is null!");
                    return;
                }

                chrt.ChartData.Activate();
                wb = (Excel.Workbook)chrt.ChartData.Workbook;

                if (wb == null) {
                    //logger.Warn("chart.ChartData.Workbook is null!");
                    return;
                }
                wb.Application.ScreenUpdating = false;
                wb.Application.WindowState = Microsoft.Office.Interop.Excel.XlWindowState.xlMinimized;

                Microsoft.Office.Interop.Excel.Worksheet wSh = (Excel.Worksheet)wb.Worksheets[1];

                if (wSh == null) {
                    //logger.Warn("chart.ChartData.Workbook.Worksheets[1] is null!");
                    return;
                }

                // save formats
                wSh.Cells.ClearContents();
                Microsoft.Office.Interop.Excel.Range Rng = wSh.get_Range("A1", "A1");
                Rng.get_Resize(dataArr.GetUpperBound(0) + 1, dataArr.GetUpperBound(1) + 1).Value2 = dataArr;
                chrt.SetSourceData("'Sheet1'!" + Rng.get_Resize(dataArr.GetUpperBound(0) + 1, dataArr.GetUpperBound(1) + 1).get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing), Type.Missing);
                chrt.Refresh();
                wb.Application.ScreenUpdating = true;

                wb.Close(Type.Missing, Type.Missing, Type.Missing);
            } catch (System.Runtime.InteropServices.COMException ex) {
                //logger.Warn("Update chart failed!", ex);
                //xlApp.ScreenUpdating = true;
            } finally {
                if (wb != null) {
                    try {
                        Marshal.ReleaseComObject(wb);
                    } catch { }
                }
            }
        }

        private class ExcelProcessManager {
            private bool _exits;
            public ExcelProcessManager() { }

            public void Lock() {
                _exits = Process.GetProcessesByName("EXCEL").Length > 0;
            }

            public void Release() {
                if (_exits)
                    return;

                Process[] excelproc = Process.GetProcessesByName("EXCEL");
                if (excelproc.Length > 0)
                    excelproc[0].Kill();
            }
        }
    }
}
